home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Unix / CNews / Source / relay / active.c next >
Encoding:
C/C++ Source or Header  |  1991-10-23  |  5.4 KB  |  246 lines

  1. /*
  2.  * active file access functions
  3.  */
  4.  
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <ctype.h>
  8. #include <sys/types.h>
  9. #include <sys/stat.h>
  10. #include "libc.h"
  11. #include "news.h"
  12. #include "config.h"
  13. #include "active.h"
  14.  
  15. /* ordinal numbers of fields */
  16. #define CURRFIELD 2        /* current article # */
  17. #define FLAGFIELD 4        /* y/n/m/x/= flag */
  18.  
  19. /* flag field values */
  20. #define FLAGOKAY 'y'        /* ordinary unmoderated group */
  21. #define FLAGBAD 'n'        /* unmoderated but locally-restricted group */
  22. #define FLAGMOD 'm'        /* moderated group */
  23. #define FLAGNEVER 'x'        /* unwanted group: don't file in this one */
  24. #define FLAGGOTO '='        /* see another group (following) instead */
  25.  
  26. /* imports */
  27. extern char *actfind();
  28. extern statust actfload(), actfsync(), actfwrnum();
  29.  
  30. /* forwards */
  31. extern char *findflag();
  32. FORWARD char *fieldfind();
  33.  
  34. /* exports */
  35. char actrelnm[] = "active";
  36.  
  37. /* privates */
  38. static char *actmode = "r+";
  39. static FILE *actfp = NULL;
  40. static struct lastngcache {
  41.     char *lnc_ng;            /* newsgroup name */
  42.     char *lnc_line;            /* matching active file line */
  43. } lnc = { NULL, NULL };
  44.  
  45. /*
  46.  * return a pointer to the active file entry for ng
  47.  * (or a pointed-to group (by ``=group'')), or 0 if no entry exists.
  48.  * since actlook is called repeatedly for the same newsgroup,
  49.  * actlook caches the last newsgroup looked-up and the result.
  50.  */
  51. char *
  52. actlook(ang)
  53. register char *ang;
  54. {
  55.     register char *ngline, *ng, *flag;
  56.     register int loopbreak = 100;
  57.  
  58.     if (lnc.lnc_ng != NULL && STREQ(lnc.lnc_ng, ang))
  59.         return lnc.lnc_line;
  60.  
  61.     if (actload() != ST_OKAY)
  62.         return NULL;
  63.     ng = strsave(ang);
  64.     while ((ngline = actfind(actfp, ng, strlen(ng))) != NULL &&
  65.         (flag = findflag(ngline)) != NULL && *flag == FLAGGOTO &&
  66.         --loopbreak > 0) {
  67.         free(ng);
  68.             ng = strsvto(flag+1, '\n');    /* follow "=ng" pointer */
  69.     }
  70.     if (loopbreak <= 0)            /* "infinite" loop broken */
  71.         ngline = NULL;
  72.  
  73.     nnfree(&lnc.lnc_ng);
  74.     lnc.lnc_ng = ng;
  75.     lnc.lnc_line = ngline;
  76.     return ngline;
  77. }
  78.  
  79. /*
  80.  * Find the active entry for ng (or a pointed-to group (by ``=group''))
  81.  * and add inc to its 2nd field (highest number).
  82.  * Return the resultant number.
  83.  */
  84. long
  85. incartnum(ng, inc)
  86. char *ng;
  87. int inc;
  88. {
  89.     char testnum[40];
  90.     register char *line = actlook(ng);
  91.     register long nextart = -1;
  92.  
  93.     if (line != NULL) {
  94.         register char *artnum, *pastartnum;
  95.  
  96.         pastartnum = artnum = fieldfind(line, CURRFIELD);
  97.         if (artnum == NULL)
  98.             return nextart;
  99.         while (isascii(*pastartnum) && isdigit(*pastartnum))
  100.             ++pastartnum;
  101.         nextart = atol(artnum) + inc;
  102.  
  103.         /* update active file article # in place, from nextart */
  104.         if (pastartnum-artnum > sizeof testnum ||
  105.             !ltozan(testnum, nextart, pastartnum-artnum) ||
  106.             !ltozan(artnum, nextart, pastartnum-artnum)) {
  107.             (void) fprintf(stderr,
  108. "%s: article number (%ld) too big for group `%s' active field of %d digits\n",
  109.                 progname, nextart, ng, pastartnum-artnum);
  110.             return -1;
  111.         }
  112.  
  113.         /* give the implementation a chance to write line to disk */
  114.         if (actfwrnum(actfp, line) != ST_OKAY) {
  115.             warning("can't update active file", "");
  116.             nextart = -1;
  117.         }
  118.     }
  119.     return nextart;
  120. }
  121.  
  122. actread()                /* set mode: just reading */
  123. {
  124.     actmode = "r";
  125. }
  126.  
  127. /*
  128.  * Reload the active file cache.
  129.  */
  130. statust
  131. actload()
  132. {
  133.     register statust status = ST_OKAY;
  134.  
  135.     if (actfp == NULL &&
  136.         (actfp = fopenwclex(ctlfile(actrelnm), actmode)) == NULL)
  137.         status |= ST_DROPPED;
  138.     status |= actfload(actfp);
  139.     return status;
  140. }
  141.  
  142. /*
  143.  * Write back to disk the active file cache, if any, and flush the
  144.  * last-newsgroup-cache, since it refers to the (now invalid) active file cache.
  145.  */
  146. statust
  147. actsync()
  148. {
  149.     register statust status = ST_OKAY;
  150.  
  151.     if (actfp != NULL) {
  152.         nnfree(&lnc.lnc_ng);
  153.         lnc.lnc_ng = lnc.lnc_line = NULL;
  154.         status |= actfsync(actfp);
  155.         if (nfclose(actfp) == EOF || status != ST_OKAY) {
  156.             warning("error writing `%s'", ctlfile(actrelnm));
  157.             status |= ST_DROPPED;
  158.         }
  159.     }
  160.     actfp = NULL;
  161.     return status;
  162. }
  163.  
  164. /*
  165.  * Return YES iff any group in ngs (or a pointed-to group (by ``=group''))
  166.  * matches thisflag.
  167.  */
  168. boolean
  169. isflag(ngs, thisflag)
  170. register char *ngs;
  171. int thisflag;
  172. {
  173.     register char *newng, *flag, *ng;
  174.     register boolean result = NO;
  175.  
  176.     for (ng = ngs; !result && ng != NULL; ng = newng) {
  177.         newng = strchr(ng, NGSEP);
  178.         if (newng != NULL)
  179.             *newng = '\0';        /* restored below */
  180.  
  181.         flag = findflag(actlook(ng));
  182.         if (flag != NULL && *flag == thisflag)
  183.             result = YES;
  184.  
  185.         if (newng != NULL)
  186.             *newng++ = NGSEP;    /* point at next group */
  187.     }
  188.     return result;
  189. }
  190.  
  191. STATIC char *
  192. fieldfind(ngline, fieldno)    /* return address of field "fieldno" in ngline */
  193. register char *ngline;
  194. register int fieldno;
  195. {
  196.     register int field;
  197.  
  198.     for (field = 1; ngline != NULL && field < fieldno; ++field) {
  199.         ngline = strchr(ngline, ' ');
  200.         if (ngline != NULL)
  201.             ngline++;        /* point at next field */
  202.     }
  203.     return ngline;
  204. }
  205.  
  206. char *
  207. findflag(ngline)        /* return address of flag field in ngline */
  208. register char *ngline;
  209. {
  210.     return fieldfind(ngline, FLAGFIELD);
  211. }
  212.  
  213. /*
  214.  * Are any groups in ngs moderated?
  215.  */
  216. boolean
  217. moderated(ngs)
  218. register char *ngs;
  219. {
  220.     return isflag(ngs, FLAGMOD);
  221. }
  222.  
  223. /*
  224.  * Are any groups in ngs unwanted?
  225.  */
  226. boolean
  227. unwanted(ngs)
  228. register char *ngs;
  229. {
  230.     return isflag(ngs, FLAGNEVER);
  231. }
  232.  
  233. /*
  234.  * Return 0 or a malloced newsgroup name corresponding to "ong",
  235.  * but without an "=" flag in its active file entry.
  236.  * This is done by tracing the chain of "=ng" pointers (in actlook()), if any.
  237.  */
  238. char *
  239. realngname(ong)
  240. char *ong;
  241. {
  242.     register char *ngline = actlook(ong);
  243.  
  244.     return (ngline == NULL? NULL: strsvto(ngline, ' '));
  245. }
  246.